package com.lww.smartbathroom.service.impl;

import com.lww.smartbathroom.model.Equipment;
import com.lww.smartbathroom.model.User;
import com.lww.smartbathroom.model.UserRecord;
import com.lww.smartbathroom.param.RecordParam;
import com.lww.smartbathroom.param.UserQueryParam;
import com.lww.smartbathroom.service.EquipmentService;
import com.lww.smartbathroom.service.UserRecordService;
import com.lww.smartbathroom.service.UserService;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.apache.tomcat.jni.Local;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.function.LongSupplier;

/**
 * @author lww
 * @version 1.0.0
 * @ClassName UserRecordServiceImpl.java
 * @Description TODO
 * @createTime 2021年01月24日 14:00:00
 */
@Service
public class UserRecordServiceImpl implements UserRecordService {
    private static final Logger LOG = LoggerFactory.getLogger(UserRecordServiceImpl.class);

    @Autowired
   private EquipmentService equipmentService;
    @Autowired
    private UserService userService;

    @Autowired
   private MongoTemplate mongoTemplate;
    @Override
    public UserRecord add(UserRecord userRecord) {
        if (userRecord == null) {
            LOG.error("input userRecord is null");
            return null;
        }
        userRecord.setGmtCreated(LocalDateTime.now());
        userRecord.setGmtModified(LocalDateTime.now());
        User user = userService.get(userRecord.getUserId());
        //积分+10
        if (user.getIntegral()==null){
            user.setIntegral(0);
        }
        user.setIntegral(user.getIntegral()+10);
        userService.modify(user);
        return mongoTemplate.insert(userRecord);
    }

    @Override
    public UserRecord get(String id) {
        if (!StringUtils.hasText(id)){
            LOG.error("input userRecord is null");
            return null;
        }

        return mongoTemplate.findById(id,UserRecord.class);
    }

    @Override
    public Page<UserRecord> list(RecordParam param) {
        if (param == null) {
            LOG.error("input param is null");
            return null;
        }
        Criteria criteria = new Criteria();
        List<Criteria> criteriaList = new ArrayList<>();
        if (StringUtils.hasText(param.getUserId())){
            criteriaList.add(Criteria.where("userId").is(param.getUserId()));
        }
        if (StringUtils.hasText(param.getRecordId())){
            criteriaList.add(Criteria.where("recordId").is(param.getRecordId()));
        }
        if (StringUtils.hasText(param.getStatus())){
            criteriaList.add(Criteria.where("recordStatus").is(param.getStatus()));
        }
        if (!criteriaList.isEmpty()){
            criteria.andOperator(criteriaList.toArray(new Criteria[]{}));
        }
        Query query = new Query(criteria);
        Long count = mongoTemplate.count(query, UserRecord.class);
        Pageable pageable = PageRequest.of(param.getPageNum()-1, param.getPageSize());
        query.with(pageable);
        List<UserRecord> userRecordList = mongoTemplate.find(query,UserRecord.class);
        //组装equipment
        userRecordList.forEach(e->{
            Equipment equipment = equipmentService.get(e.getEquipmentId());
            User user = userService.get(e.getUserId());
            if (user!=null){
                e.setUser(user);
                System.out.println(user.toString());
            }
            if (equipment!=null){
                e.setEquipment(equipment);
            }

        });
        // 构建分页器
        Page<UserRecord> pageResult = PageableExecutionUtils.getPage(userRecordList, pageable, new LongSupplier() {
            @Override
            public long getAsLong() {
                return count;
            }
        });
        return pageResult;
    }

    @Override
    public boolean modify(UserRecord userRecord) {
        if (userRecord==null||!StringUtils.hasText(userRecord.getId())){
            LOG.error("input userRecord or id is null");
            return false;
        }
        Query query = new Query(Criteria.where("_id").is(userRecord.getId()));
        Update update = new Update();
        if (userRecord.getEndTime()!=null){
            update.set("endTime",userRecord.getEndTime());
        }
        if (userRecord.getAmount()!=null){
            update.set("amount",userRecord.getAmount());
        }
        if (userRecord.getRecordStatus()!=null){
            update.set("recordStatus",userRecord.getRecordStatus());
        }
        update.set("gmtModified", LocalDateTime.now());
        UpdateResult updateResult = mongoTemplate.updateFirst(query,update,UserRecord.class);


        return updateResult!=null&&updateResult.getModifiedCount()>0;
    }

    @Override
    public boolean delete(String id) {
        if (!StringUtils.hasText(id)){
            LOG.error("in put id is null");
            return false;
        }
        UserRecord userRecord = new UserRecord();
        userRecord.setId(id);
        DeleteResult result = mongoTemplate.remove(userRecord);
        return result!=null&&result.getDeletedCount()>0;
    }

    @Override
    public long count() {
        return mongoTemplate.findAll(UserRecord.class).size();
    }

    @Override
    public double tatalPrice() {
        double result =mongoTemplate.findAll(UserRecord.class).stream().mapToDouble(UserRecord::getAmount).sum();
        return result;
    }


}
